﻿using System;
using UBlockly.UI;
using UnityEngine;
using UBlockly.Util;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UBlockly.Compotent;
using UBlockly.Scriptable;
using UBlockly.Graphic;

namespace UBlockly.Sys
{

    public partial class WorkSpaceSystem
    {
        public void LoadNodes(int classify, List<Node> nodeList)
        {
            List<RectTransform> rectList = new List<RectTransform>(nodeList.Count);
            foreach (var node in nodeList)
            {
                var item = InstanceLeftBarNode(node);
                if (node.Block != null)
                {
                    node.Block.EventHandler.OnBeginDragDel = OnSideNodeBeginDrag;
                    node.Block.EventHandler.OnClickDel = OnSideNodeClicked;
                    node.Block.EventHandler.OnDraggingDel = OnSideNodeDrag;
                    node.Block.EventHandler.OnDropDel = OnSideNodeDrop;
                }
                rectList.Add(item.GetComponent<RectTransform>());
            }
            m_SideBar.AddToLeftBar(classify, rectList.ToArray());
        }
        public bool RemoveNode(Node node)
        {
            if (node.IsBelongAnther())
                return false;
            blockEntry.BlockSystem.RemoveBlock(node.Block);
            nodeList.Remove(node);
            node.Dispose();
            return true;
        }
        public bool RemoveChain(LinkedListNode<Node> listHead)
        {
            var list = listHead.List;
            var p = listHead.List.Last;
            while (p != null)
            {
                list.RemoveLast();
                blockEntry.BlockSystem.RemoveBlock(p.Value.Block);
                nodeList.Remove(p.Value);
                p.Value.Dispose();
                p = list.Last;
            }
            return true;
        }
        public Node FindNode(long id)
        {
            return nodeList.Find(x => x.Id == id);
        }
    }

    partial class WorkSpaceSystem
    {
        private UBlockEntry blockEntry;
        UBlocklyPhysic m_BlockPhysic;
        ISideBarHandler m_SideBar;
        Transform m_NodeRootTransform;
        List<Node> nodeList = new List<Node>(300);
        Dictionary<int, BlockDescribeData> m_SideBarData;

        internal WorkSpaceSystem(UBlockEntry entry)
        {
            blockEntry = entry;
            m_BlockPhysic = entry.BlockPhysic;
            m_NodeRootTransform = entry.BlockPhysic.NodeRootTransform;
            m_SideBar = entry.BlockPhysic.SideBarHandler;
        }

        public void AddToSpace(Node node)
        {
            node.Init();
            nodeList.Add(node);
            blockEntry.BlockSystem.AddBlock(node.Block);
            node.Block.transform.SetParent(m_NodeRootTransform);
            //事件
            node.Block.EventHandler.OnBeginDragDel = OnNodeBeginDrag;
            node.Block.EventHandler.OnDraggingDel = OnNodeDrag;
            node.Block.EventHandler.OnDropDel = OnNodeDrop;
            node.Block.EventHandler.OnClickDel = OnNodeClick;
            node.Block.EventHandler.OnParamSelectedDel = OnNodeParamSelect;
            node.Block.EventHandler.OnParamDeselectedDel = OnNodeParamDeselect;
        }

        Transform InstanceLeftBarNode(Node node)
        {
            RectTransform rectp = new GameObject("RectP").AddCompontentIfNoExist<RectTransform>();
            rectp.anchorMin = new Vector2(0, 1);
            rectp.anchorMax = new Vector2(0, 1);
            rectp.pivot = new Vector2(0, 1);
            if(node.Block == null)
                Debug.LogError($"null block {node.Scriptable.GetFunc().FunName}");
            rectp.sizeDelta = node.Block.GetSize();
            node.Block.transform.SetParent(rectp);
            node.Block.transform.localPosition = Vector3.zero;
            //事件
            node.Block.EventHandler.OnParamSelectedDel = OnNodeParamSelect;
            node.Block.EventHandler.OnParamDeselectedDel = OnNodeParamDeselect;
            return rectp;
        }
        void OnSideNodeBeginDrag(PointerEventData data,BlockObject block)
        {
            var newBlock = GameObject.Instantiate(block.gameObject);
            newBlock.name = block.name;  //函数名字对应
            var sideNode = BlockGraphic.CreateNode(newBlock.GetComponent<BlockObject>());
            sideNode.Block.transform.SetParent(block.Parent);
            sideNode.Block.transform.localScale = Vector3.one;
            sideNode.Block.transform.localPosition = Vector3.zero;
            sideNode.Block.EventHandler.OnBeginDragDel = OnSideNodeBeginDrag;
            sideNode.Block.EventHandler.OnClickDel = OnSideNodeClicked;
            sideNode.Block.EventHandler.OnDraggingDel = OnSideNodeDrag;
            sideNode.Block.EventHandler.OnDropDel = OnSideNodeDrop;

            var spaceNode = block.Node.Value;
            AddToSpace(spaceNode);
            blockEntry.PaintingSystem.HandlerBlock(spaceNode.Block);
            blockEntry.NodeHandlerSystem.NodeBeginDragHandler(data, spaceNode.Block, true);
        }
        void OnSideNodeClicked(PointerEventData data, BlockObject block)
        {
            blockEntry.NodeHandlerSystem.NodeClickHandler(data, block, true);
        }
        void OnSideNodeDrag(PointerEventData data, BlockObject block)
        {
            DragBlock(data, block, true);
            blockEntry.NodeHandlerSystem.NodeDragHandler(data, block, true);
        }
        void OnSideNodeDrop(PointerEventData data, BlockObject block)
        {
            if (enterSideBarFlag)
                blockEntry.NodeHandlerSystem.NodeDropSideBarHandler(data, block, true);
            else
                blockEntry.NodeHandlerSystem.NodeDropSpaceHandler(data, block, true);

            if (block != null)
            {
                blockEntry.PaintingSystem.HandlerOver(block);
                blockEntry.NodeHandlerSystem.NodeAddToSpaceHandler(block);
            }
        }

        void OnNodeBeginDrag(PointerEventData data, BlockObject block)
        {
            offset =data.position - block.RectTransform.anchoredPosition;
            blockEntry.PaintingSystem.HandlerBlock(block);
            blockEntry.NodeHandlerSystem.NodeBeginDragHandler(data, block, false);
        }

        private Vector3 offset;
        void OnNodeDrag(PointerEventData data,BlockObject block)
        {
            DragBlock(data, block,false);
            blockEntry.NodeHandlerSystem.NodeDragHandler(data, block, false);
        }
        void OnNodeDrop(PointerEventData data,BlockObject block)
        {
            blockEntry.PaintingSystem.HandlerOver(block);
            if (enterSideBarFlag)
            {
                blockEntry.NodeHandlerSystem.NodeDropSideBarHandler(data, block, false);
            }
            else
            {
                blockEntry.NodeHandlerSystem.NodeDropSpaceHandler(data, block, false);
            }
        }
        void OnNodeClick(PointerEventData data,BlockObject block)
        {
            blockEntry.NodeHandlerSystem.NodeClickHandler(data, block, false);
        }
        void OnNodeEnterSideBar(PointerEventData data, BlockObject block,bool isSideBarNode)
        {
            enterSideBarFlag = true;
            blockEntry.NodeHandlerSystem.NodeEnterSideBarHandler(data, block, isSideBarNode);
        }
        void OnNodeExitSideBar(PointerEventData data, BlockObject block, bool isSideBarNode)
        {
            enterSideBarFlag = false;
            blockEntry.NodeHandlerSystem.NodeExitSideBarHandler(data, block, isSideBarNode);
        }

        void OnNodeParamSelect(IParamGetterCompotent paramObj)
        {
            blockEntry.NodeHandlerSystem.NodeParamSelectHandler(paramObj);
        }

        void OnNodeParamDeselect(IParamGetterCompotent paramObj)
        {
            blockEntry.NodeHandlerSystem.NodeParamDeselectHandler(paramObj);
        }

        bool IsEnterSideBar(BlockObject block)
        {
            if (m_SideBar == null)
                return false;
            return UBlockExtension.IsRecttransAcross(block.RectTransform, m_SideBar.rectTransform);
        }
        void DragBlock(PointerEventData data, BlockObject block,bool isSideNode)
        {
            var rt = block.RectTransform;

            Vector3 globalMousePos;
            if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, data.position, data.pressEventCamera, out globalMousePos))
            {
                rt.position = globalMousePos; //+ new Vector3(data.delta.x, data.delta.y);// data.delta;
            }
            if (!enterSideBarFlag && IsEnterSideBar(block))
            {
                OnNodeEnterSideBar(data, block, isSideNode);
            }
            else if (enterSideBarFlag && !IsEnterSideBar(block))
            {
                OnNodeExitSideBar(data, block, isSideNode);
            }
        }
        bool enterSideBarFlag = false;
    }
}